#pragma once

class Texture;

template<typename T>
class UIButton : public UIElement
{
	typedef void (T::*Callback)(UIButton<T>*);
	Texture* m_textureUp, *m_textureDown, *m_textureOver, *m_textureDis;
	CFont m_text;
	std::string m_szText;
	T* m_instance;
	Callback OnClick;
	bool m_hover;
	Vertex3FRHWT vertices[4];
public:
	UIButton(T* instance, Vertex2F position, Vertex2F size, std::string szText = "", i32 iTextEntry = -1) : m_text("Fonts\\ArialN.ttf", "Arial Narrow", 5)
	{
		m_hover = false;
		OnClick = 0;
		m_instance = instance;
		m_szText = sLocale.GetLocale(iTextEntry, szText);
		m_position = position;
		m_size = size;
		m_visible = true;
		m_textureUp = CTextureHandler::GetInstance()->GetTexture("Interface\\Buttons\\UI-Panel-Button-Up.blp");
		m_textureDown = CTextureHandler::GetInstance()->GetTexture("Interface\\Buttons\\UI-Panel-Button-Down.blp");
		m_textureDis = 0;
		
		vertices[0].z = vertices[1].z = vertices[2].z = vertices[3].z = 0.0f;
		vertices[0].rhw = vertices[1].rhw = vertices[2].rhw = vertices[3].rhw = 1.0f;
		vertices[0].x = position.x;
		vertices[0].y = position.y;
		vertices[0].u = 0.015f;
		vertices[0].v = 0.04f;

		vertices[1].x = position.x + size.x;
		vertices[1].y = position.y;
		vertices[1].u = 0.62f;
		vertices[1].v = 0.04f;

		vertices[2].x = position.x + size.x;
		vertices[2].y = position.y + size.y;
		vertices[2].u = 0.62f;
		vertices[2].v = 0.68f;

		vertices[3].x = position.x;
		vertices[3].y = position.y + size.y;
		vertices[3].u = 0.015f;
		vertices[3].v = 0.68f;

		m_state = 0;
	}

	void ModPosition(i32 dx, i32 dy)
	{
		m_position.x += dx;
		m_position.y += dy;

		vertices[0].x = m_position.x;
		vertices[0].y = m_position.y;

		vertices[1].x = m_position.x + m_size.x;
		vertices[1].y = m_position.y;

		vertices[2].x = m_position.x + m_size.x;
		vertices[2].y = m_position.y + m_size.y;

		vertices[3].x = m_position.x;
		vertices[3].y = m_position.y + m_size.y;
	}

	void SetTextures(std::string texUp, std::string texDown, std::string texDis = "")
	{
		m_textureUp->DecRef();
		m_textureDown->DecRef();
		if(m_textureDis)
			m_textureDis = m_textureDis->DecRef();
		m_textureUp = CTextureHandler::GetInstance()->GetTexture(texUp);
		m_textureDown = CTextureHandler::GetInstance()->GetTexture(texDown);
		if(texDis != "")
			m_textureDis = CTextureHandler::GetInstance()->GetTexture(texDis);
	}

	void SetCoordinates(Vertex2F coordinates[4])
	{
		for(ui32 i = 0; i < 4; ++i)
		{
			vertices[i].u = coordinates[i].x;
			vertices[i].v = coordinates[i].y;
		}
	}

	void SetOnClick(Callback pFunc)
	{
		OnClick = pFunc;
	}

	void OnMouseClick()
	{
		if(OnClick && m_instance)
			(m_instance->*OnClick)(this);
	}

	void Draw()
	{
		if(!m_visible || !m_textureUp)
			return;
		sD3D->SetFVF(VERTEX3FRHWT);
		bool drawn = false;
		if(!m_enabled && m_textureDis)
		{
			sD3D->SetTexture(0, *m_textureDis);
			drawn = true;
		}
		if(!m_state && !drawn)
		{
			HRESULT res = sD3D->SetTexture(0, *m_textureUp);
			if(FAILED(res))
			{
				char debug[255];
				sprintf(debug, "SetTexture failed: %X\n", res);
				OutputDebugString(debug);
			}
		}
		else if(m_state && !drawn)
			sD3D->SetTexture(0, *m_textureDown);
		sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertices, sizeof(Vertex3FRHWT));
		ui32 fontLen = m_text.GetTextLen(m_szText, true);
		ui32 x = ui32((m_position.x + (m_size.x / 2.0f)) - (fontLen / 2.0f) + (m_size.x / 30.0f));
		ui32 fontWidth = m_text.GetFontHeight(true);
		ui32 y = ui32((m_position.y + (m_size.y / 2.0f)) - (fontWidth / 2.0f));
		if(m_state)
			y += (ui32)(m_size.y / 20.0f);
		m_text.DrawTextA(x, y, m_text.GetTextLen(m_szText), m_text.GetFontHeight(), m_szText);
	}

	void OnMouseMove(ui32 x, ui32 y, bool left, bool up)
	{
		if(x >= m_position.x && x <= m_position.x + m_size.x && y >= m_position.y && y <= m_position.y + m_size.y)
			m_hover = true;
		else
			m_hover = false;
	}

	void* pData;
};